package io.elegant.sessions

import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import com.google.protobuf.Any
import io.elegant.*
import io.grpc.stub.StreamObserver
import kotlinx.coroutines.launch
import org.json.JSONArray
import org.json.JSONObject

class SensorSession(
    stub: ElegantApiGrpc.ElegantApiStub,
    private val context: Context
) : BaseSession(stub, context) {
    override val sendStreamObserver: StreamObserver<Elegant.Interaction> = stub.sensor(receiveStreamObserver)
    private var sensorManager: SensorManager? = null
    private var sensorListener: SensorEventListener? = null

    override fun onCreate(sessionId: Long, futureId: Long, vararg argv: Any) {
        super.onCreate(sessionId, futureId, *argv)
        sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
    }

    override suspend fun onDestroy(throwable: Throwable?) {
        super.onDestroy(throwable)
        if (sensorListener != null) {
            sensorManager?.unregisterListener(sensorListener)
            sensorListener = null
        }
    }

    override suspend fun onReceive(name: String, sessionId: Long, futureId: Long, vararg argv: Any) {
        when (name) {
            "getList" -> getList(sessionId, futureId, *argv)
            "getDefault" -> getDefault(sessionId, futureId, *argv)
            "registerListener" -> registerListener(*argv)
            "unregisterListener" -> unregisterListener()
            else -> super.onReceive(name, sessionId, futureId, *argv)
        }
    }

    private fun getList(sessionId: Long, futureId: Long, vararg argv: Any) {
        val type = argv[0].toIntValue()
        val allSensors = getSensors(type).toAny()
        sendAction("onGetList", sessionId, futureId, allSensors)
    }

    private fun getDefault(sessionId: Long, futureId: Long, vararg argv: Any) {
        val type = argv[0].toIntValue()
        val sensor = sensorManager?.getDefaultSensor(type)
        val res = sensor?.type ?: -1  // 默认传感器如果获取不到，返回-1
        sendAction("onGetDefault", sessionId, futureId, res.toAny())
    }

    private fun registerListener(vararg argv: Any) {
        val type = argv[0].toIntValue()
        val samplingPeriodUs = argv[3].toIntValue()
        val sensor = sensorManager?.getDefaultSensor(type)

        sensorListener = object : SensorEventListener {
            override fun onSensorChanged(evt: SensorEvent?) {
                val value1 = evt!!.values[0]
                val value2 = if (evt.values.size > 1) evt.values[1] else 0
                val value3 = if (evt.values.size > 2) evt.values[2] else 0
                csMain.launch {
                    argv[1].sendCallback(value1.toAny(), value2.toAny(), value3.toAny())
                }
            }

            override fun onAccuracyChanged(evt: Sensor?, accuracy: Int) {
                csMain.launch {
                    argv[2].sendCallback(accuracy.toAny())
                }
            }
        }
        sensorManager?.registerListener(sensorListener, sensor, samplingPeriodUs)
        SensorManager.SENSOR_DELAY_NORMAL
    }

    private fun unregisterListener(){
        if (sensorListener != null) {
            sensorManager?.unregisterListener(sensorListener)
            sensorListener = null
        }
    }

    private fun getSensors(type: Int): String {
        val deviceSensors: List<Sensor> = sensorManager?.getSensorList(type)!!
        val jsonArray = JSONArray()
        for (sensor in deviceSensors) {
            val jsonObject = JSONObject()

            jsonObject.put("type", sensor.type) // 传感器类型
            jsonObject.put("name", sensor.name ?: "") // 传感器名称
            jsonObject.put("vendor", sensor.vendor ?: "") // 传感器供应商
            jsonObject.put("version", sensor.version) // 传感器版本
            jsonObject.put("maxRange", sensor.maximumRange) // 传感器最大范围
            jsonObject.put("resolution", sensor.resolution) // 传感器分辨率
            jsonObject.put("power", sensor.power) // 传感器功耗
            jsonObject.put("minDelay", sensor.minDelay) // 传感器最小延迟
            jsonObject.put("fifoReservedEventCount", sensor.fifoReservedEventCount) // FIFO缓冲区保留事件数量
            jsonObject.put("fifoMaxEventCount", sensor.fifoMaxEventCount) // FIFO缓冲区最大事件数量
            jsonObject.put("reportingMode", sensor.reportingMode) // 报告模式
            jsonObject.put("isWakeUpSensor", sensor.isWakeUpSensor) // 是否为唤醒传感器

            jsonArray.put(jsonObject)
        }
        return jsonArray.toString()
    }
}